# _*_ coding:utf-8 _*_
"""
__Author__    :  Icy
__Date__      :  2018/5/2
__File__      :  main.py
__Desc__      :
"""
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
import os

from bson import ObjectId

from helpers.utils import AuthBackend, encry_passwd
import datetime
from optsql.model import DB
from tornado.web import RequestHandler
from tornado.options import define, options
from tornado.websocket import WebSocketHandler


class BaseHandler(RequestHandler):
	def get_current_user(self):
		uname = self.get_secure_cookie('username')
		if not uname:
			return None
		user = DB.check_user(**{"username": uname.decode("utf8")})
		return user


class IndexHandler(BaseHandler):
	@tornado.web.authenticated
	def get(self, *args, **kwargs):
		self.render('index.html', user=self.current_user, friends=DB.get_firends(self.current_user))


class SingleChatHandler(BaseHandler, WebSocketHandler):
	to_users = dict()

	def check_origin(self, origin):
		return True

	def open(self, *args, **kwargs):
		print('on opened')
		minn = kwargs.get('to_user')  # 从路由关键字获取信息
		maxx = str(self.current_user.get("_id"))
		unique_key = self._grant_key(minn, maxx)
		# 通过两者的id去验证是否建立连接
		if unique_key not in SingleChatHandler.to_users:
			SingleChatHandler.to_users[unique_key] = [self]
		else:
			# 两者的两个连接
			SingleChatHandler.to_users[unique_key].append(self)

	def _get_chat_channel(self):
		to_user = DB.check_user(_id=self._make_id)

		DB.get_or_create_chat(self.current_user['_id'], to_user['_id'], to_user['username'])

	@property
	def _make_id(self):
		minn = self.path_kwargs.get("to_user")
		to_user = ObjectId(minn)
		return to_user

	def on_message(self, message):
		# 得到聊天模型
		self._get_chat_channel()
		to_user = DB.check_user(_id=self._make_id)
		mess = DB.create_message(self.current_user['_id'],
		                         self.current_user['username'],
		                         message)
		print(mess)
		DB.add_message_to_chat(mess, self.current_user, to_user)

		unique_key = self._grant_key(self.path_kwargs.get('to_user'),
		                             str(self.current_user.get("_id")))

		messs = DB.find_message(**{"_id": mess})
		uname = self.current_user['username']
		for entile in SingleChatHandler.to_users[unique_key]:
			# 传字典会被理解为json格式
			print(',,,,', entile, uname, messs, sep='-----')
			entile.write_message(f"{uname}--"
			                     f"{messs['timestamp'].strftime('%Y-%m-%d %H:%M:%S')}--send--"
			                     f"{message}")

	def on_close(self):
		unique_key = self._grant_key(self.path_kwargs.get('to_user'), str(self.current_user.get("_id")))
		if unique_key in SingleChatHandler.to_users:
			SingleChatHandler.to_users[unique_key].remove(self)
			if len(SingleChatHandler.to_users[unique_key]) == 0:
				del SingleChatHandler.to_users[unique_key]

	def _grant_key(self, ida, idb):
		minn, maxx = ida, idb
		if minn > maxx:
			minn, maxx = maxx, minn
		unique_key = f'{minn[:5]}_{maxx[:5]}'
		return unique_key


class RoomChatHandler(WebSocketHandler, BaseHandler):
	users = set()

	def open(self, *args, **kwargs):
		self.users.add(self)
		for u in self.users:
			u.write_message('[{0}]-[{1}]进入聊天室'.format(self.request.remote_ip,
			                                          datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

	def on_message(self, message):
		# 向在线用户广播消息
		for u in self.users:
			u.write_message(u"[{0}]-[{1}]-说：{2}".format(self.request.remote_ip,
			                                            datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))

	def on_close(self):
		self.users.remove(self)
		for u in self.users:
			u.write_message(
				u"[%s]-[%s]-离开聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

	def check_origin(self, origin):
		return True


class LoginHandler(BaseHandler):
	def get(self, *args, **kwargs):
		self.render('login.html')

	def post(self, *args, **kwargs):
		username = self.get_argument('username')
		passwd = self.get_argument('passwd')
		if AuthBackend.authticate(username, passwd):
			print('login')
			AuthBackend.login(self)
			self.redirect('/')
		else:
			self.write("登陆失败")


class LogoutHandler(BaseHandler):
	def get(self, *args, **kwargs):
		if self.get_argument('logout', None):
			self.clear_cookie("username")
			self.redirect('/')


class RegisterHandler(BaseHandler):
	def get(self, *args, **kwargs):
		self.render('register.html')

	def post(self, *args, **kwargs):
		try:
			self._check_argument()
		except AuthError as e:
			self.render('register.html', error=e)
		except Exception as e:
			self.render('register.html', error=e)
		else:
			self._create_user()
			self.redirect('/login')

	def _check_argument(self):
		username = self.get_argument('username')
		email = self.get_argument('email')
		# **妙用
		if DB.check_user(**{'username': username}):
			raise AuthError("用户名已注册")
		elif DB.check_user(**{'email': email}):
			raise AuthError("邮箱已注册")
		return True

	def _create_user(self):
		username = self.get_argument('username')
		email = self.get_argument('email')
		passwd = self.get_argument('passwd')
		passwd = encry_passwd(passwd)
		user_info = {
			'username': username,
			'passwd': passwd,
			'email': email,
			'is_active': True,
			'date_joined': datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S"),
			'is_superuser': False,
		}
		DB.create_user(**user_info)


class AuthError(Exception):
	def __init__(self, msg):
		super(AuthError, self).__init__(msg)
